package shadow

import (
	"errors"
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/golang-jwt/jwt/v5"
	"golang.org/x/crypto/bcrypt"
)

var(
	secret []byte
)

type Claims struct {
    UserID   int    `json:"user_id"`
    Username string `json:"username"`
    jwt.RegisteredClaims
}

func InitJWT(){
	secret = []byte("secret-1101-22")
}

// 生成加盐哈希密码
func HashPassword(password string) (string, error) {
    bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
    return string(bytes), err
}

// 验证密码
func CheckPasswordHash(password, hash string) bool {
    err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
    return err == nil
}


//生成jwt token
func GenerateJWT(uid int,usr string) (string,error){
	 // 创建claims
    claims := Claims{
        UserID:   uid,
        Username: usr,
        RegisteredClaims: jwt.RegisteredClaims{
            ExpiresAt: jwt.NewNumericDate(time.Now().Add(12 * time.Hour)), // 24小时过期
            IssuedAt:  jwt.NewNumericDate(time.Now()),
            Issuer:    "flyfight",
        },
    }

    // 创建token
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    
    
    // 签名并获取完整的token字符串
    tokenString, err := token.SignedString(secret)
    return "Bearer "+tokenString, err
}

//解析Jwt
func ParseToken(tokenString string) (*Claims, error) {

    // 检查 Bearer 前缀
    bearerToken := strings.Split(tokenString, " ")
        if len(bearerToken) != 2 || bearerToken[0] != "Bearer" {
            log.Println("No Bearer")
           return nil,errors.New("invalid authorization format")
    }
    tokenString = bearerToken[1]
    // 解析token
    token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (any, error) {
        // 验证签名方法
        if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
        }
        return secret, nil
    })

    if err != nil {
        return nil, err
    }

    // 验证token是否有效并提取claims
    if claims, ok := token.Claims.(*Claims); ok && token.Valid {
        return claims, nil
    }

    return nil, fmt.Errorf("invalid token")
}
